/*
*    Phantom Test Driver v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
 * PTDScriptThread.java
 *
 * Created on November 5, 2005, 4:32 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package ptd;

import java.util.logging.Level;
import java.util.logging.Logger;
import ssi_socket.*;
import java.io.*;
import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * @author John
 */
public class PTDScriptThread extends java.lang.Thread{
    protected PTDScriptComm pW;                 // Parent window to accept output
    protected PTDDisplay Disp;                 // Parent window to accept output    
    
    //private String Host;                      // PC host for communication
    //private int Port;                         // Port number
    protected boolean bPrompt;                  // Flag whether to prompt
    protected boolean bDoDisplay;               // this is a jacked up way to do things

    protected int RunState;                     // Current Run State (RUNNING or STOPPED)
    protected int RunType;                      // Run type (CONSOLE or SCRIPT)
    
    protected String ScriptPath;                // Script path if running a script
    protected String Arguments;
    
    public boolean bDebug;
    public boolean bProcessor;
    
    public int runID = 0;
    
    public static int THREAD_RUNNING = 1;
    public static int THREAD_STOPPED = 2;
    
    public static int TYPE_CONSOLE   = 1;
    public static int TYPE_SCRIPT    = 2;
    
    public static int GlobalRunState = 2;
    
    private static boolean bProcessorRunning = false;
    private static boolean bProcessorLocked = false;
    
    
    // BUFFERFLUSHTASK ///////////////////////////////////////
    // BUFFER -------
    //public class BufferFlushTask extends TimerTask{
    //    public PTDScriptThread CallingThread;
    //
    //    // -----------------------------------------------------
    //    public BufferFlushTask(PTDScriptThread InCallingThread){
    //        CallingThread = InCallingThread;
    //    }
    //    public void run(){
    //        // Ensure the buffer is nor already locked
    //        try{
    //            while(CallingThread.BufferLock()){
    //                CallingThread.sleep(1);
    //            }
    //        }catch(Exception e){
    //            Main.debug_out(e.getMessage());
    //        }
    //        CallingThread.LockBuffer(true);
    //        
    //        //CallingThread.pW.display("Flush...");
    //        
    //        CallingThread.pW.display(CallingThread.OutputBuffer);
    //        CallingThread.OutputBuffer = "";
    //        CallingThread.LockBuffer(false);
    //    }            
    //}
    // END BUFFERFLUSHTASK ///////////////////////////////////////

    // -----------------------------------------------------
    public PTDScriptThread(PTDScriptComm InComm, PTDDisplay InDisp, boolean bDoDisp){
        pW = InComm;
        Disp = InDisp;
        bDoDisplay = bDoDisp;
        
        //ClientProc = null;          
        bPrompt = true;
        RunState = THREAD_STOPPED;

        //ClientApp = PTDOptions.m_DefaultAgent;
                        
        RunType = TYPE_CONSOLE;
        bDebug = false;
        bProcessor = false;
        Arguments = "";
    }

    
    //public void init(String NewHost, int NewPort, boolean NewPrompt){
    public void init(boolean NewPrompt){
        //Host = NewHost;
        //Port = NewPort;
        bPrompt = NewPrompt;
    }

    public void setScript(String InScript){
        ScriptPath = InScript;
        RunType = TYPE_SCRIPT;
    }

    public void setArguments(String InArgs){
        Arguments = InArgs;
    }
    
//JNIEXPORT void JNICALL Java_ptd_PTDScriptThread_displayHelloWorld(JNIEnv *, jobject);
//JNIEXPORT jstring JNICALL Java_ptd_PTDScriptThread_getLine(JNIEnv *, jobject, jstring);
//JNIEXPORT jint JNICALL Java_ptd_PTDScriptThread_generateScript(JNIEnv *env, jobject obj, jstring script, jstring externals, jint doPROCESSOR);
//JNIEXPORT jint JNICALL Java_ptd_PTDScriptThread_runScript(JNIEnv *, jobject, jint);
//JNIEXPORT jint JNICALL Java_ptd_PTDScriptThread_runRemoteScript(JNIEnv *env, jobject obj, jstring script, jstring host, jint port, jint doDEBUG);
//JNIEXPORT jint JNICALL Java_ptd_PTDScriptThread_runConsole(JNIEnv *, jobject, jstring);
//JNIEXPORT jint JNICALL Java_ptd_PTDScriptThread_killScript(JNIEnv *env, jobject obj, int ID);

//JNIEXPORT jstring JNICALL Java_ptd_PTDScriptThread_getVariableValue(JNIEnv *, jobject, jstring, int ID);
//JNIEXPORT jint JNICALL Java_ptd_PTDScriptThread_processDebug(JNIEnv *, jobject, jstring);
//JNIEXPORT jint JNICALL Java_ptd_PTDScriptThread_getDebugLine(JNIEnv *, jobject, int ID);
//JNIEXPORT jstring JNICALL Java_ptd_PTDScriptThread_getDebugFile(JNIEnv *, jobject, int ID);

    
    private native int initPTD(Object MainFrame);
    //private native int generateScript(String script, String externals, int bProcessor);
    private native int getScriptID();
    protected native int getRemoteID();
    //private native int runScript(String script, String args, String externals, int bProcessor, int bDebug, int ID);
    private native int runScript(String script, String args, String externals, PTDSuiteDisplay OutDisp, int bDebug, int ID);
    //private native int runScript(int bDebug, int ID);
    private native int runConsole(String externals);
    protected native int runRemoteScript(String script, String args, String Host, int Port, int bDebug, int ID);
    //public native String getVariableValue(String sVar, int ID);
    //public native int processDebug(String sCommand);
    //public native int getDebugLine(int ID);
    //public native String getDebugFile(int ID);
    public native int killScript(int ID);
    public native int killRemoteScript(int ID);
    
    public static native String getPhantomInfo(String externals);
    
    //public native void displayHelloWorld();
    
    public static String getPhantomInfo(){
        String ExternalsPath = Main.getAppDir();
        String s = getPhantomInfo(ExternalsPath);    
        return s;
    }
    
    
    public static int init_dll(){
        String JavaClient = Main.getAppDir()+"/JavaClient.dll";

        File aFile = new File(JavaClient);
        if(aFile.exists() == false){
            PTDMessageBox.MessageBox("JavaClient.dll missing.  Please re-install PTD.");
            return 0;
        }
        
        try{
            System.load(JavaClient);
        }catch (Exception e){
            return 0;
        }
        return 1;
    }    
    
    
    
    public void display(String s, int Type){
        if(s==null){
            return;
        }
        if(Type < 0){  // Garbage... throw away
        }else if(Type == 0){
            pW.display(s);
        }else{
            display_special(s, Type);
        }         
    }
    
    public void displayVar(String s){       
        pW.displayDebug(s);
    }
    
    public void display_special(String s, int Type){
        if(Type == 1){
            pW.displayError(s);        
        }else if(Type == 2){
            pW.displayWarning(s);
        }else{
            pW.displayFailure(s);
        }
    }
    
    public String getdebug(String LineInfo){
        
        String Info = LineInfo;
        if(pW.requestDebug(Info)==0){
            try{
                this.sleep(100);
             }catch(Exception e){
                Main.debug_out(e.getMessage());
            }   
            return "";
        }
        return pW.getDebugCmd();
        
    }
            
    public String getline(){
        try{
            while(pW.lineAvailable() == false){
                this.sleep(100);
            }
        }catch(Exception e){
            Main.debug_out(e.getMessage());
        }
        String s = pW.getNextLine();
        
        if(s == null){
            return "";
        }
        return s;
    }
    
    // -----------------------------------------------------
    public void run(){
     
        if(PTDMain.bJavaClientInitialized == false){
            pW.displayFailure("Run unsuccessful - PTD initialization failed.");
            return;
        }
        
        String ExternalsPath = Main.getAppDir();
        
        RunState = THREAD_RUNNING;
        if(RunType == TYPE_CONSOLE){                        
            runConsole(ExternalsPath);
        }else{
            // Required for object synchronization
            synchronized (Main.sSyncObject){
                if(bDoDisplay){
                    Disp.startScript(ScriptPath);
                }
                int iDebug = 0;
                PTDSuiteDisplay OutDisp = null;
                if(bProcessor){
                    if(initPTD((Object)Main.getMainFrame()) == 0){
                        pW.displayFailure("Preprocessor PTD Initialization Failed\n");
                    }else{
                        //iProcess = 1;
                        OutDisp = ((PTDHTMLPane)Disp).OutputDisplay;
                    }
                }

                if(bDebug){
                    iDebug = 1;
                }

                GlobalRunState = THREAD_RUNNING;  // This is to ensure only one script run at a time
                Main.getMainFrame().setCurrentScriptThread(this);

                runID = getScriptID();//generateScript(ScriptPath, ExternalsPath, iProcess);
                if(runID == 0){
                    pW.displayFailure("Could not generate script processor\n");
                    return; 
                }

                //if(bProcessor){
                //    while(getProcessorState() == true){
                //        try {
                //            Main.debug_out("PREPROC WAITING...\n");
                //            sleep(1000);
                //        } catch (InterruptedException ex) {
                //        }
                //    }
                //    setProcessorState(true);
                //}
                Main.debug_out("START PREPROC" + ScriptPath + "\n");
                //runScript(ScriptPath, Arguments, ExternalsPath, iProcess, iDebug, runID);            

                try{

                        runScript(ScriptPath, Arguments, ExternalsPath, OutDisp, iDebug, runID);            

                }catch (Exception e){
                    Main.debug_out(" +++++ OVERFLOW +++++ " + e.getMessage());
                }
                Main.debug_out("STOP PREPROC" + ScriptPath + "\n");
                //if(bProcessor){
                //    setProcessorState(false);
                //}
                Main.getMainFrame().setCurrentScriptThread(null);
                GlobalRunState = THREAD_STOPPED;
                if(bDoDisplay){
                    Disp.stopScript();
                }
            }
        }
        CleanUp();
    }
    
    public int getRunState(){
        return RunState;
    }

    // -----------------------------------------------------
    public void CleanUp(){
        Main.debug_out("Stopping script thread...");
        RunState = THREAD_STOPPED;
        if(PTDMain.bJavaClientInitialized){
            killScript(runID);
        }else{
            pW.displayFailure("Error in JavaClient.dll - reinstall PTD");
        }
        runID = 0;
        pW.setRunState(0);
    }

    // -----------------------------------------------------
    public void Kill(){
        CleanUp();
    }
    
    // -----------------------------------------------------
    public void setProcessorState(boolean bState){
        bProcessorLocked = true;
        bProcessorRunning = bState;
        bProcessorLocked = false;
    }
    
    // -----------------------------------------------------
    public boolean getProcessorState(){
        while(bProcessorLocked == true){
            try {
                sleep(2);
            } catch (InterruptedException ex) {
                Main.debug_out(ex.getMessage());
            }
        }
        return bProcessorRunning;
    }
    
    public PTDDisplay getDisp(){
        return Disp;
    }
    
}


